﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ComparableSet.cs" company="" />
//
// <summary>
//   Defines a derivative of 'HashSet' generic which can be compared and supply differences.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Utilities
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Defines a derivative of 'List' generic which can be compared and supply differences.
    /// </summary>
    /// <typeparam name="T">The type of the items in the <see cref="HashSet{T}"/></typeparam>
    public class ComparableSet<T> : List<T>, IEquatable<ComparableSet<T>>
        where T : IEquatable<T>
    {
        #region Implementation of 'IEquatable<ComparableSet<T>>'

        public bool Equals(ComparableSet<T> other)
        {
            if (Count != other.Count)
            {
                return false;
            }

            return !this.Except(other).Any() && !other.Except(this).Any();
        }

        #endregion

        #region Overides of 'object'

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            var thisType = obj as ComparableSet<T>;
            if (thisType != null)
            {
                return Equals(thisType);
            }

            return Equals(this, obj);
        }

        public override int GetHashCode()
        {
            return this.Aggregate(0, (current, item) => current ^ item.GetHashCode());
        }

        public override string ToString()
        {
            var result = new StringBuilder();

            foreach (var item in this)
            {
                result.Append(item);
            }

            return result.ToString();
        }

        #endregion
    }
}
